package cn.sprouting.tool;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.RandomUtil;
import cn.sprouting.model.Area;
import cn.sprouting.model.IdCard;
import cn.sprouting.model.common.Constant;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 生成身份证
 * @Date 创建时间： 2021/11/4. 10:13
 * @Author ：LX
 * 地点：长沙麓谷
 * 备注说明：
 */
public class RandomIDCardTool {


    /**
     * 生成身份证相关数据
     * @param num 生成数量
     * @param provinceCodeList 是否指定生成指定省的地区信息，注意，省市代码长度，可以为null
     * @param startDate 出生日期范围起始,不指定则使用 1950-01-01
     * @param endDate 出生日期范围结束，不指定则使用 2021-01-01
     * @param gender 性别 {@link cn.sprouting.model.common.Constant.SexInteger} ,不指定则随机
     * @return
     */
    public static List<IdCard> getIDCard(Integer num, List<String> provinceCodeList, Date startDate, Date endDate, Integer gender){
        if (startDate == null){
            startDate = DateUtil.parse("1950-01-01", DatePattern.NORM_DATE_PATTERN);
        }
        if (endDate == null){
            endDate = DateUtil.parse("2021-01-01", DatePattern.NORM_DATE_PATTERN);
        }
        // 性别如果没填写，则随机
        boolean isNull = false;
        if (gender == null){
            isNull = true;
        }

        List<Area> areaList = RandomAreaTool.getArea(num, provinceCodeList, null, null);
        if (areaList == null){
            return null;
        }

        Map<String, Area> collect = areaList.stream().collect(Collectors.toMap(obj -> obj.getCountyCode().substring(0, 6), Function.identity()));

        // 最终返回
        List<IdCard> saveList = new ArrayList<>();
        for (Map.Entry<String, Area> entry : collect.entrySet()){

            //随机日期 7-14
            long indexDate = RandomUtil.randomLong(startDate.getTime(), endDate.getTime());
            DateTime dateRandom = DateUtil.date(indexDate);
            String format = DateUtil.format(dateRandom, DatePattern.PURE_DATE_PATTERN);

            //随机3位顺序码 15-17
            int seq = RandomUtil.randomInt(1, 1000);
            if (isNull){
                gender = RandomUtil.randomInt(0, 2);
            }
            if (gender == 0 && seq % 2 != 0) {
                //女性，但顺序码为奇数，则强转为偶数
                seq = seq - 1;
            } else if (gender == 1 && seq % 2 == 0) {
                //男性，但顺序码为偶数，则强转为奇数
                seq = seq + 1;
            }

            //前缀+日期+顺序码
            String src = entry.getKey() + format + String.format("%03d", seq);
            //生成校验码 18
            char verifyCode = getVerifyCode(src);
            // 最终的身份证
            String card = src + verifyCode;

            // 组合
            IdCard idCard = new IdCard();
            idCard.setCardNo(card);
            idCard.setBirthday(IdcardUtil.getBirth(card));
            idCard.setSex(IdcardUtil.getGenderByIdCard(card));
            if (Constant.SexInteger.MALE.equals(idCard.getSex())){
                idCard.setSexName("男");
            } else {
                idCard.setSexName("女");
            }
            idCard.setProvince(entry.getValue().getProvince());
            idCard.setProvinceCode(entry.getValue().getProvinceCode().substring(0, 6));
            idCard.setCity(entry.getValue().getCity());
            idCard.setCityCode(entry.getValue().getCityCode().substring(0, 6));
            idCard.setCounty(entry.getValue().getCounty());
            idCard.setCountyCode(entry.getValue().getCountyCode().substring(0, 6));

            saveList.add(idCard);
        }

        return saveList;
    }

    /**
     * 计算校验码
     * @param cardId
     * @return
     */
    private static char getVerifyCode(String cardId) {
        char[] ValCodeArr = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
        int[] Wi = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
        int tmp = 0;
        for (int i = 0; i < Wi.length; i++) {
            tmp += Integer.parseInt(String.valueOf(cardId.charAt(i))) * Wi[i];
        }
        return ValCodeArr[tmp % 11];
    }

}
